﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Automata\Base\Alphabet.cs
 * Description  :     Class Alphabet which implements the interface IAlphabet
 * Change log   :     -22 Feb 2013: Some polishment, some method addition
 *                    -16 Feb 2013:  First version
 * To Do        :
 ************************************************************************/
using System;
using System.Collections.Generic;

namespace SMLib.Automata.Base
{
	/// <summary>
	/// An implementation of alphabet. Alphabet is a collection of ISymbols.
	/// </summary>
	public class Alphabet
	{
		List<ISymbol> symbols;

		/// <summary>
		/// Constructor
		/// </summary>
		public Alphabet ()
		{
			symbols = new List<ISymbol> ();
		}

		/// <summary>
		/// Add ISymbol to this alphabet.
		/// </summary>
		/// <param name="symbol">The symbol to be added</param>
		public void AddSymbol (ISymbol symbol)
		{
			symbols.Add (symbol);
		}

		/// <summary>
		/// Add some ISymbols to this alphabet
		/// </summary>
		/// <param name="symbols">array of symbols to be added</param>
		public void AddSymbols (params ISymbol[] symbols)
		{
			foreach (ISymbol symb in symbols)
				this.symbols.Add (symb);
		}

		/// <summary>
		/// Remove a symbol from list of symbols
		/// </summary>
		/// <param name="symbol">the symbol to be removed</param>
		/// <returns>true if removed, false if not exited</returns>
		public bool RemoveSymbol (ISymbol symbol)
		{
			for (int i=0; i<symbols.Count; i++)
				if (symbols [i].Equals (symbol)) {
					symbols.RemoveAt (i);
					return true;        	
				}
			return false;
		}

		/// <summary>
		/// Check it contains a symbol or not!
		/// </summary>
		/// <param name="symbol">The symbol to be searched in the alphabet</param>
		/// <returns>true if the symbol existed, false in other case</returns>
		public bool Contains (ISymbol symbol)
		{
			foreach (ISymbol symb in symbols)
				if (symb.Equals (symbol))
					return true;
			return false;
		}

		/// <summary>
		/// Clear the alphabet
		/// </summary>
		public void Clear ()
		{
			symbols.Clear ();
		}

		/// <summary>
		/// Getting the list of symbols exist in this alphabet
		/// TODO: remove it!
		/// </summary>
		/// <returns>a list of all ISymbol objects in this alphabet</returns>
		public List<ISymbol> AllSymbols ()
		{
			return symbols;
		}

		/// <summary>
		/// Return number of smybols in this alphabet.
		/// </summary>
		/// <returns>the number of ISymbols in the alphabet</returns>
		public int Size {
			get {
				return symbols.Count;
			}
		}

		public override string ToString ()
		{
			String str = ("{");
			bool first = true;
			foreach (ISymbol s in symbols) {
				str += ((first ? "" : ",") + s);
				first = false;
			}
			str += ("}");
			return str;
		}

		/// <summary>
		/// Rank of the symbol in alphabet [to use in lexico-comparison of words/pairs]
		/// </summary>
		/// <param name="symb">a symbol</param>
		/// <returns>rank of the symbol in the alphabet or -1 if it is not in alphabet</returns>
		public int Rank (ISymbol symb)
		{
			for (int i = 0; i < Size; i++) {
				if (symbols [i].Equals (symb))
					return i;
			}
			return -1;
		}

		/// <summary>
		/// i-th symbol of the alphabet
		/// </summary>
		/// <param name="i">index i</param>
		/// <returns>the i-th symbol</returns>
		public ISymbol this [int i] {
			get { return symbols [i]; }
		}
	}
}
